package com.qf.common.base.handler;


import com.qf.common.base.exception.ControllerException;
import com.qf.common.base.exception.DaoException;
import com.qf.common.base.exception.ServiceException;
import com.qf.common.base.result.ResponseResult;
import com.qf.common.base.result.ResultCode;
import com.qf.common.base.vo.ErrorsData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@RestControllerAdvice
@Slf4j
public class GlobalHandlerException {

    @ExceptionHandler(Exception.class)
    public ResponseResult<Object> handlerException(Exception ex){
        //日志
        log.error(ex.getMessage());
            /*大异常 系统级别异常*/
        return ResponseResult.error();
    }


    @ExceptionHandler(DaoException.class)
    public ResponseResult<Object> handlerException(DaoException ex){
        return ResponseResult.error(ex.getResultCode());
    }

    @ExceptionHandler(ServiceException.class)
    public ResponseResult<Object> handlerException(ServiceException ex){
        return ResponseResult.error(ex.getResultCode());
    }

    @ExceptionHandler(ControllerException.class)
    public ResponseResult<Object> handlerException(ControllerException ex){
        return ResponseResult.error(ex.getResultCode());
    }

    /**
     * 单个参数校验的时候抛出的异常
     * errors:集合
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseResult<Object> handlerConstraintViolationException(ConstraintViolationException ex){
        //针对普通校验 简单的错误信息(快速校验拿到第一个就行例如 get(0))
        ArrayList<String> errors = new ArrayList<>();
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        constraintViolations.forEach(constraintViolation -> {
            //获取注解上msg属性的值
            errors.add(constraintViolation.getMessage());
        });
        return ResponseResult.error(ResultCode.PARAMS_IS_INVALID,errors);
    }


    /**
     * 对象参数校验的时候抛出的异常(BindException)
     * errors:集合
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(value = {MethodArgumentNotValidException.class,BindException.class})
    public ResponseResult<Object> handlerBindException(BindException ex){

        //传统写法
        //allErrors->属性加信息
    /*    List<ObjectError> allErrors = ex.getAllErrors();
        //储存属性错误信息
        ArrayList<ErrorsData> errors = new ArrayList<>();
        allErrors.forEach(error->{
           errors.add(new ErrorsData(error.getObjectName(),error.getDefaultMessage()));
        });*/

        //Stream流写法
      /*  Stream<ObjectError> stream = ex.getAllErrors().stream();
        stream.map(ObjectError::getDefaultMessage);
        List<ObjectError> list = stream.collect(Collectors.toList());*/

        List<String> errors = ex.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.toList());
        return ResponseResult.error(ResultCode.PARAMS_IS_INVALID,errors);
    }
}
